Skip to content

Conversation

@mariiaKraievska
Copy link
Contributor

Description

Describe the changes made and why they were made. (Ignore if these details are present on the associated Apache Fineract JIRA ticket.)

Checklist

Please make sure these boxes are checked before submitting your pull request - thanks!

  • Write the commit message as per our guidelines
  • Acknowledge that we will not review PRs that are not passing the build ("green") - it is your responsibility to get a proposed PR to pass the build, not primarily the project's maintainers.
  • Create/update unit or integration tests for verifying the changes made.
  • Follow our coding conventions.
  • Add required Swagger annotation and update API documentation at fineract-provider/src/main/resources/static/legacy-docs/apiLive.htm with details of any API changes
  • This PR must not be a "code dump". Large changes can be made in a branch, with assistance. Ask for help on the developer mailing list.

Your assigned reviewer(s) will follow our guidelines for code reviews.

@mariiaKraievska mariiaKraievska force-pushed the FINERACT-2412/full-term-tranche-schedule-handling-and-calculation branch 2 times, most recently from ff77199 to ee3752c Compare January 7, 2026 14:21
@adamsaghy adamsaghy force-pushed the FINERACT-2412/full-term-tranche-schedule-handling-and-calculation branch from ee3752c to 926421f Compare January 8, 2026 14:06
@adamsaghy adamsaghy marked this pull request as ready for review January 8, 2026 17:37
final LocalDate firstDisbursedPeriodStartDate = firstDisbursedPeriod.isPresent() ? firstDisbursedPeriod.get().getFromDate()
: scheduleModel.getMaturityDate();

final LoanApplicationTerms loanApplicationTerms = new LoanApplicationTerms.Builder()
Copy link
Contributor

@Aman-Mittal Aman-Mittal Jan 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this LoanAplicationBuilder Logic must be extracted to an new helper function. So that it is easier to read.

and group this chaining maybe like this?

// Loan basics
.currency(...)
.principal(...)
.repaymentsStartingFromDate(...)

// Term & frequency
.loanTermFrequency(...)
.numberOfRepayments(...)
.repaymentEvery(...)
.repaymentPeriodFrequencyType(...)

// Interest configuration
.interestRatePerPeriod(...)
.annualNominalInterestRate(...)
.interestRatePeriodFrequencyType(...)
.interestMethod(...)

// Day count conventions
.daysInMonthType(...)
.daysInYearType(...)
.daysInYearCustomStrategy(...)

// Flags & options
.isDownPaymentEnabled(false)
.allowPartialPeriodInterestCalculation(...)

// Technical
.mc(mc)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

@mariiaKraievska mariiaKraievska force-pushed the FINERACT-2412/full-term-tranche-schedule-handling-and-calculation branch from 926421f to cdaf5bc Compare January 9, 2026 10:17
Copy link
Contributor

@Aman-Mittal Aman-Mittal left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code wise seems ok, Not reviewed based on e2e tests due to my lack of functional knowlegede.

Message to Maintainer: Please cross-check the tests before merge

@mariiaKraievska mariiaKraievska force-pushed the FINERACT-2412/full-term-tranche-schedule-handling-and-calculation branch 2 times, most recently from 8ddfbe7 to 1c4cb36 Compare January 9, 2026 15:25
Money amortizableAmount = disbursementTransaction.getAmount(currency).minus(downPaymentAmount);
emiCalculator.addDisbursement(model, transactionDate, amortizableAmount);

if (loan.isAllowFullTermForTranche() && loan.getNumberOfRepayments() > 0) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We are already updating the installments by model as part of recalculateRepaymentPeriodsWithEMICalculation. Do we really need to do it again here?

One of them should be removed, no?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

allocateOverpayment(disbursementTransaction, transactionCtx);
}

private void updateInstallmentsByModel(final LoanTransaction loanTransaction, final ProgressiveTransactionCtx ctx) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Check whether recalculateRepaymentPeriodsWithEMICalculation and updateInstallmentsByModel is duplication.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed updateInstallmentsByModel

if (outstandingBalanceCalculation == null) {
outstandingBalanceCalculation = Memo.of(() -> {
if (getInterestPeriods().isEmpty()) {
return getZero();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why would be the outstanding loan balance zero if there are no interest periods?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed

.mc(mc).build();
}

private void mergeNewInterestScheduleModelWithExistingOne(final ProgressiveLoanInterestScheduleModel scheduleModel,
Copy link
Contributor

@adamsaghy adamsaghy Jan 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Misleading name, use something like this instead: mergeNewScheduleModelWithExistingOne

Copy link
Contributor

@adamsaghy adamsaghy Jan 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We already have a mergeNewInterestScheduleModelWithExistingOne function. Is his duplicate? Can we have just one?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mergeNewInterestScheduleModelWithExistingOne for re-aging actually has the different approach, I renamed it accordinally

* * Generates temporary interestScheduleModel with particular disbursement date
*/
@NotNull
private ProgressiveLoanInterestScheduleModel generateTemporaryScheduleModelWithParticularDisbursementDate(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We already have a generateTemporaryReAgedScheduleModel function. Is this duplicate? Can we have just one?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, you are right, left just one of them

Copy link
Contributor

@adamsaghy adamsaghy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Kindly see my review!

@mariiaKraievska mariiaKraievska force-pushed the FINERACT-2412/full-term-tranche-schedule-handling-and-calculation branch from 1c4cb36 to b817f5b Compare January 13, 2026 12:13
loanTransaction.getLoan(), installmentCounter.get(), rm.getFromDate(), rm.getDueDate(),
rm.getDuePrincipal().getAmount(), null, null, null, null, null, null, null, false, false, false);

if (rm.getDueInterest().isGreaterThanZero()) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We dont need this. Set interest in the constructor.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

installment.updateObligationsMet(currency, transactionDate);
} else {
if (model.loanProductRelatedDetail().isAllowFullTermForTranche()
&& loanTransaction.getLoan().getNumberOfRepayments() > 0 && !rm.getDueDate().isBefore(transactionDate)) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can fetch this from the model.loanProductRelatedDetail()

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

@mariiaKraievska mariiaKraievska force-pushed the FINERACT-2412/full-term-tranche-schedule-handling-and-calculation branch from b817f5b to d931e77 Compare January 13, 2026 14:39
@mariiaKraievska mariiaKraievska marked this pull request as draft January 13, 2026 14:55
@mariiaKraievska mariiaKraievska force-pushed the FINERACT-2412/full-term-tranche-schedule-handling-and-calculation branch from d931e77 to 58f9ddc Compare January 13, 2026 15:44
@mariiaKraievska mariiaKraievska marked this pull request as ready for review January 13, 2026 15:46
@adamsaghy adamsaghy merged commit 09031aa into apache:develop Jan 13, 2026
35 checks passed
@adamsaghy adamsaghy deleted the FINERACT-2412/full-term-tranche-schedule-handling-and-calculation branch January 13, 2026 17:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants